{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "# How to disable parallel tool calling\n",
        "\n",
        "```{=mdx}\n",
        ":::info Prerequisites\n",
        "\n",
        "This guide assumes familiarity with the following concepts:\n",
        "\n",
        "- [LangChain Tools](/docs/concepts/tools)\n",
        "- [Tool calling](/docs/concepts/tool_calling)\n",
        "- [Custom tools](/docs/how_to/custom_tools)\n",
        "\n",
        ":::\n",
        "```\n",
        "\n",
        ":::info OpenAI-specific\n",
        "\n",
        "This API is currently only supported by OpenAI.\n",
        "\n",
        ":::\n",
        "\n",
        "OpenAI models perform tool calling in parallel by default. That means that if we ask a question like `\"What is the weather in Tokyo, New York, and Chicago?\"` and we have a tool for getting the weather, it will call the tool 3 times in parallel. We can force it to call only a single tool once by using the `parallel_tool_call` call option."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "First let's set up our tools and model:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 1,
      "metadata": {},
      "outputs": [],
      "source": [
        "import { ChatOpenAI } from \"@langchain/openai\";\n",
        "import { z } from \"zod\";\n",
        "import { tool } from \"@langchain/core/tools\";\n",
        "\n",
        "const adderTool = tool(async ({ a, b }) => {\n",
        "  return a + b;\n",
        "}, {\n",
        "  name: \"add\",\n",
        "  description: \"Adds a and b\",\n",
        "  schema: z.object({\n",
        "    a: z.number(),\n",
        "    b: z.number(),\n",
        "  })\n",
        "});\n",
        "\n",
        "const multiplyTool = tool(async ({ a, b }) => {\n",
        "  return a * b;\n",
        "}, {\n",
        "  name: \"multiply\",\n",
        "  description: \"Multiplies a and b\",\n",
        "  schema: z.object({\n",
        "    a: z.number(),\n",
        "    b: z.number(),\n",
        "  })\n",
        "});\n",
        "\n",
        "const tools = [adderTool, multiplyTool];\n",
        "\n",
        "const llm = new ChatOpenAI({\n",
        "  model: \"gpt-4o-mini\",\n",
        "  temperature: 0,\n",
        "});"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "Now let's show a quick example of how disabling parallel tool calls work:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 2,
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "[\n",
            "  {\n",
            "    name: 'add',\n",
            "    args: { a: 5, b: 3 },\n",
            "    type: 'tool_call',\n",
            "    id: 'call_5bKOYerdQU6J5ERJJYnzYsGn'\n",
            "  }\n",
            "]\n"
          ]
        }
      ],
      "source": [
        "const llmWithTools = llm.bindTools(tools, { parallel_tool_calls: false });\n",
        "\n",
        "const result = await llmWithTools.invoke(\"Please call the first tool two times\");\n",
        "\n",
        "result.tool_calls;"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "As we can see, even though we explicitly told the model to call a tool twice, by disabling parallel tool calls the model was constrained to only calling one.\n",
        "\n",
        "Compare this to calling the model without passing `parallel_tool_calls` as false:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 3,
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "[\n",
            "  {\n",
            "    name: 'add',\n",
            "    args: { a: 1, b: 2 },\n",
            "    type: 'tool_call',\n",
            "    id: 'call_Ni0tF0nNtY66BBwB5vEP6oI4'\n",
            "  },\n",
            "  {\n",
            "    name: 'add',\n",
            "    args: { a: 3, b: 4 },\n",
            "    type: 'tool_call',\n",
            "    id: 'call_XucnTCfFqP1JBs3LtbOq5w3d'\n",
            "  }\n",
            "]\n"
          ]
        }
      ],
      "source": [
        "const llmWithNoBoundParam = llm.bindTools(tools);\n",
        "\n",
        "const result2 = await llmWithNoBoundParam.invoke(\"Please call the first tool two times\");\n",
        "\n",
        "result2.tool_calls;"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "You can see that you get two tool calls.\n",
        "\n",
        "You can also pass the parameter in at runtime like this:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 4,
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "[\n",
            "  {\n",
            "    name: 'add',\n",
            "    args: { a: 1, b: 2 },\n",
            "    type: 'tool_call',\n",
            "    id: 'call_TWo6auul71NUg1p0suzBKARt'\n",
            "  }\n",
            "]\n"
          ]
        }
      ],
      "source": [
        "const result3 = await llmWithNoBoundParam.invoke(\"Please call the first tool two times\", {\n",
        "  parallel_tool_calls: false,\n",
        "});\n",
        "\n",
        "result3.tool_calls;"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Related\n",
        "\n",
        "- [How to: create custom tools](/docs/how_to/custom_tools)\n",
        "- [How to: pass run time values to tools](/docs/how_to/tool_runtime)"
      ]
    }
  ],
  "metadata": {
    "kernelspec": {
      "display_name": "TypeScript",
      "language": "typescript",
      "name": "tslab"
    },
    "language_info": {
      "codemirror_mode": {
        "mode": "typescript",
        "name": "javascript",
        "typescript": true
      },
      "file_extension": ".ts",
      "mimetype": "text/typescript",
      "name": "typescript",
      "version": "3.7.2"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 4
}
